package com.huasan.www.demon.rest.resource;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.ws.rs.Consumes;
import javax.ws.rs.CookieParam;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.glassfish.jersey.server.mvc.Viewable;
import org.springframework.beans.factory.annotation.Autowired;

import com.huasan.www.demon.data.service.UserinfoService;
import com.huasan.www.demon.pojo.Userinfo;
import com.huasan.www.demon.pojo.UserinfoExample;
import com.huasan.www.demon.rest.util.Constants;
import com.huasan.www.demon.util.DataTableUtil;
import com.huasan.www.demon.util.DemonCipher;
import com.huasan.www.demon.util.Des;
import com.huasan.www.demon.util.MD5;
import com.huasan.www.demon.util.OnePage;

@Path("/user")
public class UserInfoResource extends Resource{

	private static final String SALT = "PASSWORDSALT";
	
	@Autowired
	private UserinfoService userinfoService;
	
	private Userinfo userinfo;
	
	private DemonCipher md5 = new MD5();
	
	@GET
	@Produces("text/html")
	public Viewable getMain(){
		return getView("user", null);
	}
	
	@GET
	@Path("/add")
	@Produces("text/html")
	public Viewable getAdd(){
		return getView("user_edit", null);
	}
	
	@GET
	@Path("/edit")
	@Produces("text/html")
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public Viewable getEdit(@QueryParam("id") Integer id) {
		Map ret = new HashMap(); 
		ret.put("edit", "true");
		userinfo = userinfoService.selectByPrimaryKey(id.longValue());
		return getView( "user_edit", this,  ret );
	}
	
	@GET
	@Path("/view")
	@Produces("text/html")
	public Viewable getView(@QueryParam("id") Integer id) {
		userinfo = userinfoService.selectByPrimaryKey(id.longValue());
		return getView("user_edit", this);
	}
	
	@GET
	@Path("/recall")
	@Produces("text/html")
	public Viewable getAccountBack(@QueryParam("str1") String username,	@QueryParam("str2") String oldp, @CookieParam("JSESSIONID") String ses ){
		try {
			DemonCipher md5 = new MD5();
			DemonCipher des = new Des();
			
			Map<String,String> map = new HashMap<String,String>();
			String ref = md5.encrypt(ses);
			map.put("ref", ref);
			
			String loginname = des.decrypt(username);
			Userinfo user = this.getUserInfoByLoginName(loginname);
			if (user==null){
				return getView("recalltimeout", null);
			}
			
			String password = md5.encrypt(SALT, user.getPwd());
			if (!password.equals(oldp)){
				return getView("recalltimeout", null);
			}
			
			return getView("recall",map);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return getView("recalltimeout", null);
		}
	}
	
	@GET
	@Path("/chgpwd")
	@Produces("text/html")
	public Viewable getChangePassword(@QueryParam("str1") String username ){
		try {
			Map<String,String> map = new HashMap<String,String>();
			map.put("loginname", username);
			
			return getView("pwdchg",map);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return getView("recalltimeout", null);
		}
	}
	
	@POST
	@Path("/login")
	@Produces("text/html")
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public Response getLogin(@FormParam("loginname") String loginname, @FormParam("pwd") String pwd,
			@FormParam("remember") String remember ) throws URISyntaxException {
		Map<String, String> retMap = new HashMap<String,String>();
		try{
			userinfo = loginnameExisted(loginname, md5.encrypt(pwd));
			if (userinfo != null){
				retMap.put("userinfo", objectmapper.writeValueAsString(userinfo));
				setSession(userinfo);
				httpServletRequest.getSession().setAttribute("demonsid", userinfo.getSid());
				if ("remember".equals(remember)){
					return Response.seeOther(new URI(httpServletRequest.getRequestURL()+"/../../main"))
							.cookie(new NewCookie("demonsid", userinfo.getSid(), "/",null, null, Constants.DURATION, false))
							.build();
				}
				else{
					httpServletRequest.getSession().setAttribute("demonsid", userinfo.getSid());
					return Response.seeOther(new URI(httpServletRequest.getRequestURL()+"/../../main"))
							.cookie(new NewCookie("demonsid", null, "/",null, null, Constants.DURATION_CLEAR, false))
							.build();
				}
			}
			else{
				retMap.put("message", "用户名或密码错");
				return Response.ok(new Viewable("/WEB-INF/common/login", retMap)).build();
			}
		}catch (Exception e){
			logger.error(e.getMessage(), e);
			retMap.put("message", "登录失败，请重试");
			return Response.ok(new Viewable("/WEB-INF/common/login", retMap)).build();
		}
	}
	
	@GET
	@Path("/users2")
	@Produces({MediaType.APPLICATION_JSON} )
	public String getUsers2(@QueryParam("sEcho") String sEcho,
				@QueryParam("iDisplayStart") Integer iDisplayStart,
				@QueryParam("iDisplayLength") Integer iDisplayLength,
				@QueryParam("sSearch") String sSearch) throws JsonGenerationException, JsonMappingException, IOException{
		
		UserinfoExample example = new UserinfoExample();
		
		Integer total = userinfoService.countByExample(example);
		example.setLimitStart(iDisplayStart);
		example.setLimitEnd(iDisplayLength);
		OnePage<Userinfo> page = userinfoService.selectOnePageByExample(example);
		return DataTableUtil.getDataTable(sEcho, total, total
				, objectmapper.writeValueAsString(page.getDataList()));
	}
	
	@POST
	@Path("/users")
	@Produces({MediaType.APPLICATION_JSON} )
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public String getUsers(@FormParam("sEcho") String sEcho,
			@FormParam("iDisplayStart") Integer iDisplayStart,
			@FormParam("iDisplayLength") Integer iDisplayLength,
			@FormParam("sSearch") String sSearch,
			@FormParam("mobileno") String mobileno,
			@FormParam("cursetname") String cursetname,
			@FormParam("optname") String optname,
			@FormParam("locale") String locale
				) throws JsonGenerationException, JsonMappingException, IOException{
		UserinfoExample example = new UserinfoExample();
		UserinfoExample.Criteria criteria = example.createCriteria();
		criteria.andDeletedEqualTo("0");
		if (mobileno!=null)
			criteria.andMobilenoLike(DataTableUtil.wrapLike( mobileno ));
		if (cursetname!=null)
			criteria.andCursetnameLike(DataTableUtil.wrapLike( cursetname ));
		if (optname!=null)
			criteria.andOptnameLike(DataTableUtil.wrapLike( optname ));
		if (locale!=null)
			criteria.andLocaleLike(DataTableUtil.wrapLike( locale ));
		Integer total = userinfoService.countByExample(example);
		example.setLimitStart(iDisplayStart);
		example.setLimitEnd(iDisplayLength);
		OnePage<Userinfo> page = userinfoService.selectOnePageByExample(example);
		return DataTableUtil.getDataTable(sEcho, total, total
				, objectmapper.writeValueAsString(page.getDataList()));
	}
	
	@DELETE
	@Path("/delete")
	@Produces({MediaType.APPLICATION_JSON} )
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public String deleteUser(@FormParam("ids") List<Integer> ids) {
		try{
			for (Integer id : ids){
				Userinfo userInfo = userinfoService.selectByPrimaryKey(id.longValue());
				userInfo.setDeleted("1");
				userinfoService.updateByPrimaryKey(userInfo);
			}
			return getSucReturn("");
		}catch (Exception e){
			logger.error(e.getMessage(), e);
			return getErrReturn("");
		}
	}
	
	@PUT
	@Path("/adduser")
	@Produces({MediaType.APPLICATION_JSON} )
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public String addUser(@FormParam(value = "loginname") String loginname,
			@FormParam(value = "nickname")String nickname,
			@FormParam(value = "mobileno")String mobileno,
			@FormParam(value = "mail") String mail,
			@FormParam(value = "optname")String optname,
			@FormParam(value = "locale")String locale,
			@FormParam(value = "cursetid")Integer cursetid,
			@FormParam(value = "cursetname")String cursetname,
			@FormParam(value = "nextsetid")Integer nextsetid){
		try{
			if (loginnameExisted(loginname))
				return getErrReturn("用户已存在");
			
			Userinfo userinfo = new Userinfo();
			userinfo.setLoginname(loginname);
			userinfo.setNickname(nickname);
			userinfo.setMobileno(mobileno);
			userinfo.setMail(mail);
			userinfo.setOptname(optname);
			userinfo.setLocale(locale);
			if (cursetid!=null)
				userinfo.setCursetid(cursetid.longValue());
			userinfo.setCursetname(cursetname);
			if (nextsetid!=null){
				userinfo.setNextsetid(nextsetid.longValue());
				userinfo.setCreatetime(new Timestamp(System.currentTimeMillis()));
			}
			userinfoService.insertSelective(userinfo);
			return getSucReturn("保存成功"); 
		}catch (Exception e){
			logger.error(e.getMessage(), e);
			return getErrReturn("保存失败，请重试");
		}
	}
	
	@PUT
	@Path("/saveuser")
	@Produces({MediaType.APPLICATION_JSON} )
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public String saveUser(@FormParam(value = "id") Integer id,
			@FormParam(value = "loginname") String loginname,
			@FormParam(value = "nickname")String nickname,
			@FormParam(value = "mobileno")String mobileno,
			@FormParam(value = "mail") String mail,
			@FormParam(value = "optname")String optname,
			@FormParam(value = "locale")String locale,
			@FormParam(value = "cursetid")Integer cursetid,
			@FormParam(value = "cursetname")String cursetname,
			@FormParam(value = "nextsetid")Integer nextsetid){
		try{
			Userinfo userinfo = userinfoService.selectByPrimaryKey(id.longValue());
			userinfo.setLoginname(loginname);
			userinfo.setNickname(nickname);
			userinfo.setMobileno(mobileno);
			userinfo.setMail(mail);
			userinfo.setOptname(optname);
			userinfo.setLocale(locale);
			if (cursetid!=null){
				userinfo.setCursetid(cursetid.longValue());
				userinfo.setCursetname(cursetname);
			}
			if (nextsetid!=null)
				userinfo.setNextsetid(nextsetid.longValue());
			userinfo.setCreatetime(new Timestamp(System.currentTimeMillis()));
			userinfoService.updateByPrimaryKey(userinfo);
			return getSucReturn("保存成功"); 
		}catch (Exception e){
			logger.error(e.getMessage(), e);
			return getErrReturn("保存失败，请重试");
		}
	}
	
	@GET
	@Path("/namecheck")
	@Produces({MediaType.APPLICATION_JSON} )
	public String checkLoginName(@QueryParam("loginname") String name){
		if (loginnameExisted(name))
			return getErrReturn("登录名已存在");
		return getSucReturn("名称可用");
	}
	
	private Userinfo loginnameExisted(String loginname, String pwd){
		UserinfoExample example = new UserinfoExample();
		UserinfoExample.Criteria criteria = example.createCriteria();
		criteria.andLoginnameEqualTo(loginname);
		criteria.andPwdEqualTo(pwd);
		List<Userinfo> list = userinfoService.selectByExample(example);
		if (list.size()==0)
			return null;
		String sid = UUID.randomUUID().toString();
		Userinfo userinfo = list.get(0);
		userinfo.setSid(sid);
		userinfoService.updateByPrimaryKey(userinfo);
		return userinfo;
	}
	
	private boolean loginnameExisted(String loginname){
		UserinfoExample example = new UserinfoExample();
		UserinfoExample.Criteria criteria = example.createCriteria();
		criteria.andDeletedEqualTo("0");
		criteria.andLoginnameEqualTo(loginname);
		return userinfoService.countByExample(example)>0;
	}
	
	@POST
	@Path("/renewpwd")
	@Produces({MediaType.APPLICATION_JSON})
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public String setNewPassword(@FormParam("newpwd") String password, @FormParam("params") String params,
			  @FormParam("refer") String refer, @CookieParam("JSESSIONID") String ses){
		try{
			DemonCipher des = new Des();
			DemonCipher MD5 = new MD5();
			if (!MD5.encrypt(ses).equals(refer)){
				return getErrReturn("Session is out");
			}
			
			if (password==null){
				return getErrReturn("Password is NULL");
			}
			
			String[] paras = params.split("&");
			String loginname = des.decrypt(paras[0].split("=")[1]);
			Userinfo user = getUserInfoByLoginName(loginname);
			if (user.getPwd().equals(password)){
				logger.info("Reset Password Error: Save Passwords");
				return getErrReturn("Save error");
			}
			
			if (MD5.encrypt(SALT, user.getPwd()).equals(paras[1].split("=")[1])){
				user.setPwd(password);//TODO encyp
				userinfoService.updateByPrimaryKey(user);
				return getSucReturn("Change Password Successfully");
			}else {
				return getErrReturn("Validate Error");
			}
		}catch (Exception e){
			logger.error(e.getMessage(), e);
			return getErrReturn("Change Password Error");
		}
	}
	
	@POST
	@Path("/renewpwd2")
	@Produces({MediaType.APPLICATION_JSON})
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public String setNewPassword2(@FormParam("newpwd") String password, @FormParam("loginname") String loginname){
		try{
			if (password==null || "".equals(password)){
				return getErrReturn("密码为空");
			}
			Userinfo user = getUserInfoByLoginName(loginname);
			if (user==null){
				return getErrReturn("用户不存在");
			}
			DemonCipher MD5 = new MD5();
			user.setPwd(MD5.encrypt( password ));
			userinfoService.updateByPrimaryKey(user);
			return getSucReturn("Change Password Successfully");
		}catch (Exception e){
			logger.error(e.getMessage(), e);
			return getErrReturn("Change Password Error");
		}
	}
	
	@POST
	@Path("/renewpwdurl")
	@Produces({MediaType.APPLICATION_JSON})
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public String getNewPasswordUrl(@FormParam("username") String loginname){
		try {
			Userinfo user = getUserInfoByLoginName(loginname);
			if (user==null){
				return this.getErrReturn("No Such User");
			}
			DemonCipher des = new Des();
			DemonCipher MD5 = new MD5();
			String url = httpServletRequest.getScheme() + "://" + httpServletRequest.getLocalAddr() 
					+ ":" + httpServletRequest.getLocalPort()
					+ "/demon/rest/user/recall?str1="
					+ des.encrypt(loginname) + "&str2="
					+ MD5.encrypt(SALT, user.getPwd());
			//TODO Password Process
			logger.info("=================>" + url);
			return this.getSucReturn( "Send Successfully" );
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return this.getErrReturn("Process Error, Please Retry");
		}
	}
	
	@POST
	@Path("/chnpwd")
	@Produces({MediaType.APPLICATION_JSON})
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public String changePwdByUid(@FormParam("userid") Long userid,
			@FormParam("old") String oldp, @FormParam("new") String newp){
		try{
			if (oldp==null || newp==null || "".equals(oldp) || "".equals(newp)){
				return getErrReturn("Password is NULL");
			}
			
			Userinfo user = userinfoService.selectByPrimaryKey(userid);
			if (user == null)
				return getErrReturn("Can not find this user");
			
			if (oldp.equals(user.getPwd())){
				user.setPwd(newp);
				userinfoService.updateByPrimaryKey(user);
				return getSucReturn("Change pwd succussfully");
			}else {
				return getErrReturn("The old password invalidated");
			}
		}catch (Exception e){
			logger.error(e.getMessage(), e);
			return getErrReturn("Change Password Error");
		}
	}
	
	public Userinfo getUserInfoByLoginName(String loginname){
		UserinfoExample example = new UserinfoExample();
		UserinfoExample.Criteria criteria = example.createCriteria();
		criteria.andLoginnameEqualTo(loginname);
		List<Userinfo> list = userinfoService.selectByExample(example);
		if (list.size()==0)
			return null;
		return list.get(0);
	}
	
	private Map<String, String> getUserRetMap(Long id) throws JsonGenerationException, JsonMappingException, IOException{
		Map<String, String> map = new HashMap<String, String>();
		map.put(  "userinfo", objectmapper.writeValueAsString(userinfoService.selectByPrimaryKey(id) ) );
		return map;
	}

	public Userinfo getUserinfo() {
		return userinfo;
	}

	public void setUserinfo(Userinfo userinfo) {
		this.userinfo = userinfo;
	}
}
